var __pulse_stop_flg = false;

ol.Map.prototype.stopPulse = function() {
	__pulse_stop_flg = true;
}
ol.Map.prototype.pulse = function(bool, coords, options) {
	var listenerKey;
	__pulse_stop_flg = bool;
	options = options || {};

	// Change to map's projection
	if (options.projection) {
		coords = ol.proj.transform(coords, options.projection, this.getView().getProjection());
	}

	// options
	var start = new Date().getTime();
	var duration = options.duration || 3000;
	var easing = options.easing || ol.easing.easeOut;

	var style = options.style;
	if (!style) style = new ol.style.Circle({
		radius: 15,
		stroke: new ol.style.Stroke({
			color: 'red',
			width: 0
		})
	});
	if (style instanceof ol.style.Image) style = new ol.style.Style({
		image: style
	});
	if (!(style instanceof Array)) style = [style];

	var amplitude = options.amplitude || 1;
	if (amplitude < 0) amplitude = 0;

	var maxRadius = options.radius || 15;
	if (maxRadius < 0) maxRadius = 5;
	var minRadius = maxRadius - (options.amplitude || maxRadius); //options.minRadius || 0;
	var width = options.lineWidth || 2;
	var color = options.color || 'red';

	// Animate function
	function animate(event) {
		var frameState = event.frameState;
		var ratio = frameState.pixelRatio;
		var elapsed = frameState.time - start;
		if (elapsed > duration && __pulse_stop_flg) {
			ol.Observable.unByKey(listenerKey);

		} else {
			var elapsedRatio = (elapsed % duration) / duration;
			var context = event.context;
			context.save();
			context.beginPath();
			var e = easing(elapsedRatio)
			context.globalAlpha = easing(1 - elapsedRatio);
			for (var i = 0; i < style.length; i++) {
				var imgs = style[i].getImage();
				var sc = imgs.getScale();
				imgs.setScale(ratio * sc * (1 + amplitude * (e - 1)));
				event.vectorContext.setStyle(style[i]);
				event.vectorContext.drawGeometry(new ol.geom.Point(coords));
				imgs.setScale(sc);
			}
			context.restore();
			// tell OL3 to continue postcompose animation
			frameState.animate = true;
		}
	}
	// Launch animation
	listenerKey = this.on('postcompose', animate, this);
	this.renderSync();
}